package org.abettor.nookinfo.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.abettor.nookinfo.AddressConstant;
import org.abettor.nookinfo.R;
import org.abettor.nookinfo.novel.NovelDownloadManager;
import org.abettor.nookinfo.persist.NovelHelper;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;

/**
 * 下载小说的Service
 * @author shawn
 *
 */
public class NovelDownloadService extends Service
{
	public static final String NOVEL_DOWNLOAD_SERVICE_STATUS = "NOVEL_DOWNLOAD_SERVICE_STATUS";
	public static final String NOVEL_DOWNLOAD_SERVICE_CURRENT_ID = "NOVEL_DOWNLOAD_SERVICE_CURRENT_ID";
	public static final String NOVEL_DOWNLOAD_SERVICE_CURRENT_NAME = "NOVEL_DOWNLOAD_SERVICE_CURRENT_NAME";
	public static final String NOTIFICATION_TAG = "org.abettor.nookinfo.novel";
	public static final int DOWNLOAD_STATUS_BEGIN = 0;
	public static final int DOWNLOAD_STATUS_DONE = 1;
	public static final int DOWNLOAD_STATUS_ERROR = 2;
	public static final int DOWNLOAD_STATUS_CANCEL = 3;
	private NovelDownloadBinder binder = new NovelDownloadBinder();
	private NotificationManager notiMgm;
	private List<NovelDownloadTask> tasks = Collections.synchronizedList(new ArrayList<NovelDownloadTask>());

	@Override
	public IBinder onBind(Intent intent)
	{
		return binder;
	}

	@Override
	public void onCreate()
	{
		super.onCreate();
		notiMgm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

		//	服务一旦启动就不愿死去
		registerReceiverAlarm(this);
	}

	@Override
	public void onDestroy()
	{
		cancelAll();
		super.onDestroy();
	}

	/**
	 * 开始下载id指定的小说
	 */
	public boolean download(int id, String name)
	{
		//	先找到已经存在的任务
		NovelDownloadTask task = null;
		for(NovelDownloadTask t : tasks)
		{
			if(t.id == id)
			{
				task = t;
				if(t.status == DOWNLOAD_STATUS_BEGIN)
				{
					return false;
				}

				break;
			}
		}

		//	开始下载指定小说，并将其添加到任务列表
		if(task == null)
		{
			task = new NovelDownloadTask();
			tasks.add(task);
		}

		task.complete = 0;
		task.id = id;
		task.name = name;
		task.status = DOWNLOAD_STATUS_BEGIN;
		task.worker = new Worker(task);
		task.worker.start();

		//	点击显示下载管理器View
		Intent activityIntent = new Intent();
		activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_STATUS, DOWNLOAD_STATUS_BEGIN);
		activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_CURRENT_ID, id);
		activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_CURRENT_NAME, name);
		activityIntent.setClass(this, NovelDownloadManager.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, activityIntent, 0);

		String tickerText = getString(R.string.novel_download_service_working).replace("REPL", name);
		Notification noti = new Notification(android.R.drawable.stat_sys_download, tickerText, System.currentTimeMillis());
		noti.setLatestEventInfo(this, getString(R.string.novel_download_service_working_title), getString(R.string.novel_download_service_working_content).replace("REPL", name), pendingIntent);

		notiMgm.notify(NOTIFICATION_TAG, id, noti);

		return true;
	}

	/**
	 * 取消下载novel指定的小说
	 * @param novel
	 */
	public void cancel(int novel)
	{
		//	先找到已经存在的任务
		for(NovelDownloadTask t : tasks)
		{
			if(t.id == novel)
			{
				//	终止下载线程，设定当前状态为取消
				t.worker.kill();
				t.status = DOWNLOAD_STATUS_CANCEL;

				//	清除正在下载的notification
				notiMgm.cancel(NOTIFICATION_TAG, novel);

				//	通知界面
				Intent activityIntent = new Intent();
				activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_STATUS, DOWNLOAD_STATUS_CANCEL);
				activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_CURRENT_ID, t.id);
				activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_CURRENT_NAME, t.name);
				activityIntent.setClass(NovelDownloadService.this, NovelDownloadManager.class);
				PendingIntent pendingIntent = PendingIntent.getActivity(NovelDownloadService.this, 0, activityIntent, 0);
				String tickerText = getString(R.string.novel_download_service_cancel).replace("REPL", t.name);
				Notification noti = new Notification(android.R.drawable.stat_sys_warning, tickerText, System.currentTimeMillis());
				noti.setLatestEventInfo(NovelDownloadService.this, getString(R.string.novel_download_service_cancel_title), getString(R.string.novel_download_service_cancel_content).replace("REPL", t.name), pendingIntent);
				notiMgm.notify(NOTIFICATION_TAG, t.id, noti);

				return;
			}
		}
	}

	/**
	 * 取消所有正在下载的小说
	 */
	public void cancelAll()
	{
		for(NovelDownloadTask t : tasks)
		{
			//	终止下载线程，设定当前状态为取消
			t.worker.kill();
			t.status = DOWNLOAD_STATUS_CANCEL;

			//	清除正在下载的notification
			notiMgm.cancel(NOTIFICATION_TAG, t.id);
		}

		//	这里要clear吗？
		//tasks.clear();
	}

	/**
	 * 获取小说下载任务列表
	 */
	public List<NovelDownloadTask> getTasks()
	{
		return tasks;
	}

	//	注册系统定时器，以便在被杀后启动
	public static void registerReceiverAlarm(Context context)
	{
		Intent intent = new Intent(context, NovelDownloadReliveReceiver.class);
		PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
		AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
		am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + (60 * 1000), pi);
	}

	/**
	 * 小说下载服务的Binder，用于访问小说下载服务对象
	 * @author shawn
	 *
	 */
	public class NovelDownloadBinder extends Binder
	{
		/**
		 * 获取小说箱子服务类的实例
		 */
		public NovelDownloadService getService()
		{
			return NovelDownloadService.this;
		}
	}

	/**
	 * 小说下载任务
	 * @author shawn
	 *
	 */
	public class NovelDownloadTask
	{
		public int id;//小说ID
		public String name;//小说名称
		public int status;//当前状态
		public int complete;//已完成百分数
		public Worker worker;//下载工作线程，不应该被外类之外的其它类访问
	}

	/**
	 * 小说下载工作线程
	 * @author shawn
	 *
	 */
	public class Worker extends Thread
	{
		NovelHelper novelHelper = new NovelHelper(NovelDownloadService.this);
		private boolean cancel = false;
		private NovelDownloadTask task;

		public Worker(NovelDownloadTask task)
		{
			super();
			this.task = task;
		}

		/**
		 * 杀死下载线程
		 */
		public void kill()
		{
			//	杀死下载进程
			cancel = true;
			interrupt();
		}

		//	下载小说并不断更新完成状态并适时通知到状态栏
		@Override
		public void run()
		{
			//	首先获取小说基本信息，尝试3次
			int i = 0;
			NovelInfo novelInfo = null;
			while(novelInfo == null && i < 3 && ! cancel)
			{
				novelInfo = getNovelInfo(task.id);
				i ++;
			}
			if(novelInfo != null)
			{
				//	保存小说信息
				novelHelper.saveOrUpdateLocalNovel(task.id, task.name);
			}
			else if(! cancel)
			{
				//	通知失败
				task.status = DOWNLOAD_STATUS_ERROR;
				noticeStatus(task.id, task.name, false);
				return;
			}
			else
			{
				return;
			}

			//	检查是否已经下载了一些章节
			int chaperCount = 0;
			int currentChapter = novelInfo.firstChapter;
			int downloadedCount = novelHelper.getLocalChapterPageCount(task.id, 1);
			if(downloadedCount > 1)
			{
				//	如果曾经下载过，就继续下载未完成的那些章节即可（最后一章视为没有下载完成，重下）
				NovelHelper.LocalChapter lc = novelHelper.getLocalChapterList(task.id, 1, downloadedCount).get(0);
				currentChapter = lc.id;
				chaperCount = downloadedCount - 1;
				task.complete = chaperCount * 100 / novelInfo.chapters;
			}

			//	读取第“一”章，尝试3次
			i = 0;
			Chapter chapterFirst = null;
			while(chapterFirst == null && i < 3 && ! cancel)
			{
				chapterFirst = getChapter(currentChapter, false);
				i ++;
			}
			if(chapterFirst != null)
			{
				//	保存第“一”章
				chaperCount ++;
				novelHelper.saveOrUpdateChapter(chapterFirst.id, task.id, chapterFirst.name, chaperCount, chapterFirst.content);
				task.complete = chaperCount * 100 / novelInfo.chapters;
			}
			else if(! cancel)
			{
				//	通知失败
				task.status = DOWNLOAD_STATUS_ERROR;
				noticeStatus(task.id, task.name, false);
				return;
			}
			else
			{
				return;
			}

			//	读取后续章节，尝试3次
			currentChapter = chapterFirst.id;
			for(int j = downloadedCount; j < novelInfo.chapters && ! cancel; j ++)
			{
				i = 0;
				Chapter chapter = null;
				while(chapter == null && i < 3 && ! cancel)
				{
					chapter = getChapter(currentChapter, true);
					i ++;
				}
				if(chapter != null)
				{
					//	保存章节
					chaperCount ++;
					novelHelper.saveOrUpdateChapter(chapter.id, task.id, chapter.name, chaperCount, chapter.content);
					task.complete = chaperCount * 100 / novelInfo.chapters;
				}
				else if(! cancel)
				{
					//	通知失败
					task.status = DOWNLOAD_STATUS_ERROR;
					noticeStatus(task.id, task.name, false);
					return;
				}
				else
				{
					return;
				}

				//	继续往下走
				currentChapter = chapter.id;
			}

			//	通知下载完成
			if(! cancel)
			{
				task.status = DOWNLOAD_STATUS_DONE;
				noticeStatus(task.id, task.name, true);
			}
		}

		//	读取id所指定的文章章节
		private Chapter getChapter(int id, boolean isNext)
		{
			try
			{
				Chapter chapter = new Chapter();
				DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
				DocumentBuilder db = dbf.newDocumentBuilder();
				String url = AddressConstant.NOVEL_CONTENT.replace("ACTION", isNext ? "content-behind" : "content").replace("ID", id + "");
				Document doc = db.parse(url);
				String theId = doc.getElementsByTagName("id").item(0).getTextContent();
				chapter.id = Integer.parseInt(theId);
				chapter.name = doc.getElementsByTagName("name").item(0).getTextContent();
				Node contentNode = doc.getElementsByTagName("value").item(0);
				NodeList contents = contentNode.getChildNodes();
				int size = contents.getLength();
				for(int i = 0; i < size; i ++)
				{
					Node node = contents.item(i);
					if(node instanceof CDATASection)
					{
						CDATASection cdata = (CDATASection) node;
						chapter.content = cdata.getData();
						break;
					}
				}

				return chapter;
			}
			catch(Exception e)
			{
				Log.d(this.getClass().getName(), "", e);
			}

			return null;
		}
		

		//	获取指定文章的基本信息
		private NovelInfo getNovelInfo(int id)
		{
			try
			{
				NovelInfo info = new NovelInfo();

				//	先获取所有章节里的第一页
				DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
				DocumentBuilder db = dbf.newDocumentBuilder();
				String url = AddressConstant.NOVEL_CHAPTER.replace("ID", id + "").replace("PAGE", "1");
				Document doc = db.parse(url);
				NodeList list = doc.getElementsByTagName("chapter");
				int pageSize = list.getLength();
				if(pageSize > 0)
				{
					//	这是第一个章节
					Node node = list.item(0);
					NodeList children = node.getChildNodes();
					int count = children.getLength();
					for(int i = 0; i < count; i ++)
					{
						Node tmp = children.item(i);
						if("id".equals(tmp.getNodeName()))
						{
							//	找到了id字段
							String theId = tmp.getTextContent();
							info.firstChapter = Integer.parseInt(theId);
							break;
						}
					}
				}

				list = doc.getElementsByTagName("total");
				String total = list.item(0).getTextContent();
				int totalPage = Integer.parseInt(total);

				//	获取所有章节里边的最后一页
				db = dbf.newDocumentBuilder();
				url = AddressConstant.NOVEL_CHAPTER.replace("ID", id + "").replace("PAGE", total);
				doc = db.parse(url);
				list = doc.getElementsByTagName("chapter");
				int lastPageSize = list.getLength();
				info.chapters = (totalPage - 1) * pageSize + lastPageSize;

				return info;
			}
			catch(Exception e)
			{
				Log.d(this.getClass().getName(), "", e);
			}

			return null;
		}

		//	通知下载失败或完成
		private void noticeStatus(int id, String name, boolean done)
		{
			notiMgm.cancel(NOTIFICATION_TAG, id);

			Intent activityIntent = new Intent();
			activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_STATUS, done ? DOWNLOAD_STATUS_DONE : DOWNLOAD_STATUS_ERROR);
			activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_CURRENT_ID, id);
			activityIntent.putExtra(NOVEL_DOWNLOAD_SERVICE_CURRENT_NAME, name);
			activityIntent.setClass(NovelDownloadService.this, NovelDownloadManager.class);
			PendingIntent pendingIntent = PendingIntent.getActivity(NovelDownloadService.this, 0, activityIntent, 0);

			Notification noti = null;
			if(done)
			{
				String tickerText = getString(R.string.novel_download_service_done).replace("REPL", name);
				noti = new Notification(android.R.drawable.stat_sys_download_done, tickerText, System.currentTimeMillis());
				noti.setLatestEventInfo(NovelDownloadService.this, getString(R.string.novel_download_service_done_title), getString(R.string.novel_download_service_done_content).replace("REPL", name), pendingIntent);
			}
			else
			{
				String tickerText = getString(R.string.novel_download_service_error).replace("REPL", name);
				noti = new Notification(android.R.drawable.stat_sys_warning, tickerText, System.currentTimeMillis());
				noti.setLatestEventInfo(NovelDownloadService.this, getString(R.string.novel_download_service_error_title), getString(R.string.novel_download_service_error_content).replace("REPL", name), pendingIntent);
			}

			notiMgm.notify(NOTIFICATION_TAG, id, noti);
		}

		/**
		 * 文章信息
		 * @author shawn
		 *
		 */
		public class NovelInfo
		{
			public int chapters;//章节总数
			public int firstChapter;//第一章的id
		}

		/**
		 * 文章章节对象
		 * @author shawn
		 *
		 */
		public class Chapter
		{
			public int id;
			public String name;
			public String content;
		}
	}
}
